import base64

from django.utils import timezone

from app.models import Dish, Order, OrderItem, User, MerchantInfo, OrderImage, Image
from django.db import transaction
from middleware.util import make_response
from django.db import models
from middleware.util import parse_and_format_time
class OrderService:
    @staticmethod
    @transaction.atomic
    def create_order(user_id, merchant_id, items, table_number=None):
        """
        创建新订单（后端根据 dish_id 查询菜品）
        :param user_id: 用户 UUID（从 JWT 解析）
        :param merchant_id: 商家 UUID
        :param items: 菜品列表，格式为 [{"dish_id": "...", "quantity": 2, "customization": {...}]
        :param table_number: 桌号（可选）
        :return: 统一格式响应
        """
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return make_response(code=404, message="用户不存在")

        try:
            merchant = MerchantInfo.objects.get(merchant_id=merchant_id)
        except MerchantInfo.DoesNotExist:
            return make_response(code=404, message="商家不存在")

        total_amount = 0
        validated_items = []

        for item in items:
            dish_id = item.get("dish_id")
            quantity = item.get("quantity", 1)
            customization = item.get("customization")

            if not dish_id or quantity < 1:
                return make_response(code=400, message="无效的菜品ID或数量")

            try:
                dish = Dish.objects.select_for_update().get(dish_id=dish_id, merchant=merchant)
            except Dish.DoesNotExist:
                return make_response(code=404, message=f"菜品 {dish_id} 不存在或不属于该商家")

            if dish.stock < quantity:
                return make_response(code=400, message=f"{dish.dish_name} 库存不足")

            total_amount += float(dish.price) * quantity
            validated_items.append({
                "dish": dish,
                "quantity": quantity,
                "customization": customization
            })

        # 创建订单
        order = Order.objects.create(
            user=user,
            merchant=merchant,
            table_number=table_number,
            total_amount=total_amount,
            status='pending_payment'
        )

        # 创建订单项并扣减库存
        for item in validated_items:
            OrderItem.objects.create(
                order=order,
                dish=item["dish"],
                quantity=item["quantity"],
                customization=item["customization"],
                unit_price=item["dish"].price
            )
            item["dish"].stock -= item["quantity"]
            item["dish"].save()

        return make_response(
            code=201,
            message="下单成功",
            data={
                "order_id": str(order.order_id),
                "total_amount": total_amount,
                "item_count": len(validated_items)
            }
        )

    @staticmethod
    @transaction.atomic
    def rate_order(order_id, user_id, rating, comment=None, images=None):
        """
        用户对订单进行评分和评论，并可上传图片（支持排序）
        :param order_id: 订单 ID
        :param user_id: 用户 ID（确保权限）
        :param rating: 评分（1.0 ~ 5.0）
        :param comment: 评论内容（可选）
        :param images: 图片列表 [ { "data": "...", "mime_type": "...", "sort_order": 0 } ]
        :return: 统一格式响应
        """
        try:
            order = Order.objects.get(order_id=order_id)
        except Order.DoesNotExist:
            return make_response(code=404, message="订单不存在")

        if str(order.user.id) != str(user_id):
            return make_response(code=403, message="无权评价他人订单")

        if not (1 <= float(rating) <= 5):
            return make_response(code=400, message="评分范围应为 1.0 到 5.0")

        # 更新评分和评论
        order.rating = rating
        order.comment = comment
        order.save()

        image_ids = []
        for idx, img in enumerate(images or []):
            image_data = img.get("data")
            mime_type = img.get("mime_type")
            sort_order = img.get("sort_order", idx)

            if not image_data or not mime_type:
                continue

            try:
                # 🔁 将 Base64 数据解码为二进制数据
                image_binary = base64.b64decode(image_data)
            except (TypeError, ValueError) as e:
                # 处理解码失败的情况
                return make_response(code=400, message=f"图片数据无效: {e}")

            # 创建图片记录
            image = Image.objects.create(
                image_data=image_binary,
                mime_type=mime_type
            )

            # 创建订单图片关联
            OrderImage.objects.create(
                order=order,
                image=image,
                sort_order=sort_order
            )
            image_ids.append(str(image.image_id))

        return make_response(
            code=200,
            message="评分成功",
            data={
                "order_id": str(order.order_id),
                "rating": float(order.rating),
                "comment": order.comment,
                "image_count": len(image_ids)
            }
        )

    @staticmethod
    @transaction.atomic
    def cancel_order(order_id, user_id):
        """
        用户取消订单（仅限待支付状态）
        :param order_id: 订单 ID
        :param user_id: 用户 ID（从 JWT 解析）
        :return: 统一格式响应
        """
        try:
            order = Order.objects.select_for_update().get(order_id=order_id)
        except Order.DoesNotExist:
            return make_response(code=404, message="订单不存在")

        if str(order.user.id) != str(user_id):
            return make_response(code=403, message="无权操作他人订单")

        if order.status == 'completed':
            return make_response(code=400, message="已完成的订单无法取消")

        if order.status == 'cancelled':
            return make_response(code=400, message="订单已取消，请勿重复操作")

        if order.status != 'pending_payment':
            return make_response(code=400, message="非待支付状态订单不可取消")

        # 恢复库存
        for item in order.items.all():
            if item.status == 'in_preparation':  # 只恢复未完成的菜品
                dish = item.dish
                if dish:
                    dish.stock += item.quantity
                    dish.save()

        # 设置所有菜品项为 cancelled
        order.items.filter(status='in_preparation').update(status='cancelled')

        # 更新订单状态
        order.status = 'cancelled'
        order.save()

        return make_response(
            code=200,
            message="订单已成功取消，库存已恢复",
            data={
                "order_id": str(order.order_id),
                "status": order.status
            }
        )

    @staticmethod
    def pay_order(order_id, user_id):
        """
        用户支付订单（模拟）
        :param order_id: 订单 ID
        :param user_id: 用户 ID
        :return: 统一格式响应
        """
        try:
            order = Order.objects.get(order_id=order_id)
        except Order.DoesNotExist:
            return make_response(code=404, message="订单不存在")

        if str(order.user.id) != str(user_id):
            return make_response(code=403, message="无权操作他人订单")

        if order.status != 'pending_payment':
            return make_response(code=400, message="订单当前状态不可支付")

        # 开启事务，确保数据一致性
        from django.db import transaction
        with transaction.atomic():
            # 1. 更新订单状态
            order.status = 'in_preparation'
            order.save(update_fields=['status'])

            # 2. 更新所有订单项状态为 'in_preparation'
            order.items.update(status='in_preparation')

        return make_response(
            code=200,
            message="支付成功，订单进入制作流程",
            data={
                "order_id": str(order.order_id),
                "status": order.status
            }
        )

    @staticmethod
    def list_user_orders(user_id):
        """
        获取当前用户的所有订单（按时间倒序）
        :param user_id: 用户 ID（从 JWT 解析）
        :return: 统一格式响应
        """
        orders = Order.objects.filter(user_id=user_id).prefetch_related('items__dish').order_by('-create_time')
        if not orders.exists():
            return make_response(code=200, message="暂无订单", data=[])

        result = []
        for order in orders:
            items = []
            for item in order.items.all():
                items.append({
                    "dish_name": item.dish.dish_name,
                    "quantity": item.quantity,
                    "unit_price": float(item.unit_price),
                })

            result.append({
                "order_id": str(order.order_id),
                "total_amount": float(order.total_amount),
                "status": order.status,
                "table_number": order.table_number,
                "create_time": parse_and_format_time(order.create_time),
                "items": items
            })

        return make_response(
            code=200,
            message="获取成功",
            data=result
        )

    @staticmethod
    def get_order_detail(order_id, user_id):
        """
        获取某个订单的详细信息（含评分、评论、图片），图片按 sort_order 排序
        """
        try:
            order = Order.objects.get(order_id=order_id, user_id=user_id)
        except Order.DoesNotExist:
            return make_response(code=404, message="订单不存在或无权访问")

        items = []
        for item in order.items.prefetch_related('dish'):
            items.append({
                "dish_id": str(item.dish.dish_id) if item.dish else None,
                "dish_name": item.dish.dish_name if item.dish else "已下架菜品",
                "quantity": item.quantity,
                "unit_price": float(item.unit_price),
                "customization": item.customization
            })

        images = []
        for oi in order.images.select_related('image').order_by('sort_order'):
            images.append({
                "data": base64.b64encode(oi.image.image_data).decode('utf-8'),
                "mime_type": oi.image.mime_type,
                "sort_order": oi.sort_order
            })

        return make_response(
            code=200,
            message="获取成功",
            data={
                "order_id": str(order.order_id),
                "total_amount": float(order.total_amount),
                "status": order.status,
                "table_number": order.table_number,
                "create_time": order.create_time.isoformat(),
                "rating": float(order.rating) if order.rating else None,
                "comment": order.comment,
                "items": items,
                "images": images
            }
        )

    @staticmethod
    def list_merchant_orders(merchant_id):
        """
        获取商家所有订单，并按状态排序（未完成靠前）
        :param merchant_id: 商家 ID（从 JWT 解析）
        :return: 统一格式响应
        """
        try:
            orders = Order.objects.filter(merchant_id=merchant_id).prefetch_related('items__dish').order_by(
                # 自定义排序：pending_payment -> in_preparation -> others
                '-status',  # 默认字符串排序不够灵活，我们手动指定排序逻辑
            ).annotate(
                status_order=models.Case(
                    models.When(status='pending_payment', then=models.Value(0)),
                    models.When(status='in_preparation', then=models.Value(1)),
                    default=models.Value(2),
                    output_field=models.IntegerField()
                )
            ).order_by('status_order', '-create_time')

            if not orders.exists():
                return make_response(code=200, message="暂无订单", data=[])

            result = []
            for order in orders:
                items = []
                for item in order.items.all():
                    items.append({
                        "dish_name": item.dish.dish_name if item.dish else "已下架菜品",
                        "quantity": item.quantity,
                        "unit_price": float(item.unit_price),
                        "customization": item.customization
                    })

                result.append({
                    "order_id": str(order.order_id),
                    "user": order.user.username,
                    "total_amount": float(order.total_amount),
                    "status": order.status,
                    "table_number": order.table_number,
                    "create_time": order.create_time.isoformat(),
                    "items": items
                })

            return make_response(
                code=200,
                message="获取成功",
                data=result
            )

        except Exception as e:
            return make_response(code=500, message=f"系统错误：{str(e)}")

    @staticmethod
    def complete_order_item(item_id, merchant_id):
        """
        完成一个订单项（菜品）
        :param item_id: 订单项 ID
        :param merchant_id: 商家 ID（确保权限）
        :return: 统一格式响应
        """
        try:
            item = OrderItem.objects.select_related('order', 'order__merchant').get(
                id=item_id,
                order__merchant_id=merchant_id
            )
        except OrderItem.DoesNotExist:
            return make_response(code=404, message="订单项不存在或无权操作")

        if item.status == 'completed':
            return make_response(code=400, message="该菜品已标记为完成")

        # 更新菜品状态
        item.status = 'completed'
        item.completed_at = timezone.now()
        item.save()

        # 判断是否整个订单已完成
        order = item.order
        remaining_items = order.items.filter(status='in_preparation')

        if not remaining_items.exists():
            order.status = 'completed'
            order.save()

        return make_response(
            code=200,
            message="菜品状态更新成功",
            data={
                "item_id": item.id,
                "status": item.status,
                "order_status": order.status
            }
        )

    @staticmethod
    def complete_all_order_items(order_id, merchant_id):
        """
        将订单中所有菜品标记为已完成
        :param order_id: 订单 ID
        :param merchant_id: 商家 ID（权限验证）
        :return: 统一格式响应
        """
        try:
            order = Order.objects.select_related('merchant').get(
                order_id=order_id,
                merchant_id=merchant_id
            )
        except Order.DoesNotExist:
            return make_response(code=404, message="订单不存在或无权操作")

        if order.status in ['completed', 'cancelled']:
            return make_response(code=400, message="订单状态不可修改")

        # 批量更新菜品状态
        updated_count = order.items.filter(status='in_preparation').update(
            status='completed',
            completed_at=timezone.now()
        )

        # 更新订单状态为已完成
        order.status = 'completed'
        order.save()

        return make_response(
            code=200,
            message=f"成功完成 {updated_count} 道菜品，并将订单标记为已完成",
            data={
                "order_id": str(order.order_id),
                "updated_count": updated_count
            }
        )

    @staticmethod
    def list_pending_orders(merchant_id):
        """
        获取当前商家需要准备的订单（仅 pending_payment 和 in_preparation 状态）
        并列出其中尚未完成的菜品
        """
        orders = Order.objects.filter(
            merchant_id=merchant_id,
            status__in=['pending_payment', 'in_preparation']
        ).prefetch_related('items')

        if not orders.exists():
            return make_response(code=200, message="暂无待处理订单", data=[])

        result = []
        for order in orders:
            items = []
            for item in order.items.all():
                if item.status != 'completed':
                    items.append({
                        "item_id": item.id,
                        "dish_name": item.dish.dish_name if item.dish else "已下架菜品",
                        "quantity": item.quantity,
                        "unit_price": float(item.unit_price),
                        "customization": item.customization,
                        "status": item.status
                    })

            if items:
                result.append({
                    "order_id": str(order.order_id),
                    "user": order.user.username,
                    "total_amount": float(order.total_amount),
                    "table_number": order.table_number,
                    "create_time": order.create_time.isoformat(),
                    "items": items
                })

        return make_response(
            code=200,
            message="获取成功",
            data=result
        )

    @staticmethod
    @transaction.atomic
    def cancel_all_order_items(order_id, merchant_id):
        """
        商家取消订单中所有未完成的菜品项
        :param order_id: 订单 ID
        :param merchant_id: 商家 ID（权限验证）
        :return: 统一格式响应
        """
        try:
            order = Order.objects.select_related('merchant').get(
                order_id=order_id,
                merchant_id=merchant_id
            )
        except Order.DoesNotExist:
            return make_response(code=404, message="订单不存在或无权操作")

        if order.status in ['completed', 'cancelled']:
            return make_response(code=400, message="已完成或已取消的订单不可操作")

        # 获取并更新未完成的菜品项
        updated_count = order.items.filter(status='in_preparation').update(
            status='cancelled'
        )

        # 恢复库存
        for item in order.items.filter(status='in_preparation'):
            dish = item.dish
            if dish:
                dish.stock += item.quantity
                dish.save()

        # 判断是否所有菜品都已被取消或完成
        remaining_items = order.items.exclude(status__in=['completed', 'cancelled'])
        if not remaining_items.exists():
            order.status = 'cancelled'
        else:
            order.status = 'in_preparation'  # 仍保留制作中状态

        order.save()

        return make_response(
            code=200,
            message=f"成功取消 {updated_count} 道未完成菜品",
            data={
                "order_id": str(order.order_id),
                "order_status": order.status,
                "updated_count": updated_count
            }
        )

    @staticmethod
    def get_pending_dishes_by_category(merchant_id):
        """
        根据商家ID获取所有待完成的菜品，并按类别归类
        :param merchant_id: 商家UUID
        :return: 统一格式的响应
        """
        try:
            merchant = MerchantInfo.objects.get(merchant_id=merchant_id)
        except MerchantInfo.DoesNotExist:
            return make_response(code=404, message="商家不存在")

        # 查询所有“制作中”的订单项，并预加载关联数据
        order_items = OrderItem.objects.filter(
            order__merchant=merchant,
            status='in_preparation'
        ).select_related('dish', 'dish__category')

        if not order_items.exists():
            return make_response(code=200, message="当前无待完成的菜品", data={})

        # 构建结果字典：以分类名作为 key
        result = {}

        for item in order_items:
            dish = item.dish
            category_name = dish.category.category_name if dish.category else "未分类"

            # 初始化分类键
            if category_name not in result:
                result[category_name] = []

            # 添加订单项信息（已去除 username / table_number / unit_price）
            result[category_name].append({
                "dish_name": dish.dish_name,
                "item_id": item.id,
                "quantity": item.quantity,
                "customization": item.customization,
            })
            # print(item.id)

        return make_response(code=200, message="查询成功", data=result)


    @staticmethod
    def get_pending_cook_orders(merchant_id):
        """
        获取未制作的订单项（按菜品类别分组）
        :param merchant_id: 商家ID
        :return: 未制作订单列表
        """
        try:
            # 查询未制作的订单项（状态为 in_preparation 且未开始制作）
            pending_items = OrderItem.objects.filter(
                order__merchant_id=merchant_id,
                status='in_preparation',
            ).select_related('dish', 'dish__category', 'order').order_by('order__create_time')

            # 按类别分组
            categories = {}
            for item in pending_items:
                category_name = item.dish.category.category_name if item.dish and item.dish.category else "未分类"
                
                if category_name not in categories:
                    categories[category_name] = []
                
                categories[category_name].append({
                    "order_id": str(item.order.order_id),
                    "dish_id": str(item.dish.dish_id) if item.dish else None,
                    "dish_name": item.dish.dish_name if item.dish else "已删除菜品",
                    "quantity": item.quantity,
                    "customization": item.customization,
                    "table_number": item.order.table_number,
                    "order_time": item.order.create_time.isoformat(),
                    "unit_price": float(item.unit_price)
                })

            # 转换为列表格式
            result = []
            for category_name, items in categories.items():
                result.append({
                    "category_name": category_name,
                    "items": items,
                    "item_count": len(items)
                })

            return make_response(
                code=200,
                message="获取成功",
                data=result
            )

        except Exception as e:
            logger.error(f"获取未制作订单失败: merchant_id={merchant_id}, error={str(e)}")
            raise ValidationError(f"获取未制作订单失败：{str(e)}")

    @staticmethod
    def get_pending_serve_orders(merchant_id):
        """
        获取未上菜的订单项（按菜品类别分组）
        :param merchant_id: 商家ID
        :return: 未上菜订单列表
        """
        try:
            # 查询已制作完成但未上菜的订单项
            pending_serve_items = OrderItem.objects.filter(
                order__merchant_id=merchant_id,
                status='cooked'  # 新状态：已制作完成
            ).select_related('dish', 'dish__category', 'order').order_by('completed_at')

            # 按类别分组
            categories = {}
            for item in pending_serve_items:
                category_name = item.dish.category.category_name if item.dish and item.dish.category else "未分类"
                
                if category_name not in categories:
                    categories[category_name] = []
                
                categories[category_name].append({
                    "order_id": str(item.order.order_id),
                    "dish_id": str(item.dish.dish_id) if item.dish else None,
                    "dish_name": item.dish.dish_name if item.dish else "已删除菜品",
                    "quantity": item.quantity,
                    "customization": item.customization,
                    "table_number": item.order.table_number,
                    "order_time": item.order.create_time.isoformat(),
                    "completed_time": item.completed_at.isoformat() if item.completed_at else None,
                    "unit_price": float(item.unit_price)
                })

            # 转换为列表格式
            result = []
            for category_name, items in categories.items():
                result.append({
                    "category_name": category_name,
                    "items": items,
                    "item_count": len(items)
                })

            return make_response(
                code=200,
                message="获取成功",
                data=result
            )

        except Exception as e:
            logger.error(f"获取未上菜订单失败: merchant_id={merchant_id}, error={str(e)}")
            raise ValidationError(f"获取未上菜订单失败：{str(e)}")    